package com.jxin.mall.middle.util.redis;

import com.jxin.mall.middle.consts.MiddleLogMsgConsts;
import lombok.Builder;
import lombok.Data;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;

/**
 * redis和Db事物同步工具
 * @author  蔡佳新
 * @version 1.0
 * @since   jdk 1.8
 */
@Data
@Component
public class RedisDataSourceTransactionUtil {
    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;
    @Resource(name = "mutilStrProtoRedisUtil")
    private MutilStrProtoRedisUtil mutilStrProtoRedisUtil;
    /**
     * 承载RedisDataSourceTransactionUtil的工具类本身的实例
     */
    private static RedisDataSourceTransactionUtil redisDataSourceTransactionUtil;
    @PostConstruct
    private void init() {
        redisDataSourceTransactionUtil = this;
    }
    /**
     * 开始redis和DB事务 DB事物采用默认传播行为
     * @return 默认传播特性的数据库事物实例
     * @author 蔡佳新
     */
    public static TransactionStatus begin() {
        // 手动begin数据库事务
       final TransactionStatus transaction = redisDataSourceTransactionUtil.getDataSourceTransactionManager()
                                                                           .getTransaction(new DefaultTransactionAttribute());
        redisDataSourceTransactionUtil.getMutilStrProtoRedisUtil().begin();
        return transaction;
    }

    /**
     * 支持Redis与数据库事务同时提交
     * @param transactionStatus 事物状态
     * @author 蔡佳新
     */
    public static void commit(@NotNull TransactionStatus transactionStatus){
        Assert.notNull(transactionStatus, RedisDataSourceTransactionUtilMsg.NON_NULL_TRANSACTION_STATUS_REQUIRED);
        redisDataSourceTransactionUtil.getDataSourceTransactionManager().commit(transactionStatus);
    }

    /**
     * 支持Redis与数据库事务同时回滚
     * @param transactionStatus 事物状态
     * @author 蔡佳新
     */
    public static void rollback(@NotNull TransactionStatus transactionStatus){
        Assert.notNull(transactionStatus, RedisDataSourceTransactionUtilMsg.NON_NULL_TRANSACTION_STATUS_REQUIRED);
        redisDataSourceTransactionUtil.getDataSourceTransactionManager().rollback(transactionStatus);
        redisDataSourceTransactionUtil.getMutilStrProtoRedisUtil().discard();
    }

    /**
     * redis工具类 的内部消息类
     * @author  蔡佳新
     * @version 1.0
     * @since   jdk 1.8
     */
    private interface RedisDataSourceTransactionUtilMsg{
        /**transactionStatus为null的异常信息*/
        String NON_NULL_TRANSACTION_STATUS_REQUIRED = MiddleLogMsgConsts.REDIS_UTIL + "non null transactionStatus required";
    }

}
